package com.haier.npt.security.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.haier.npt.exception.BizBaseException;
import com.haier.npt.page.PageBean;
import com.haier.npt.security.dao.SysPermissionDao;
import com.haier.npt.security.dao.SysRoleDao;
import com.haier.npt.security.dao.SysRoleMemberReDao;
import com.haier.npt.security.dao.SysRolePermissionReDao;
import com.haier.npt.security.domain.SysPermission;
import com.haier.npt.security.domain.SysRole;
import com.haier.npt.security.domain.SysRoleMemberRe;
import com.haier.npt.security.domain.SysRolePermissionRe;
import com.haier.npt.security.dto.SysRoleDTO;
import com.haier.npt.security.dto.SysRoleSystemDTO;
import com.haier.npt.security.i18n.SecurityExceptionCode;
import com.haier.npt.security.i18n.SecurityMessageCode;
import com.haier.npt.security.service.SysRoleService;
import com.haier.npt.utils.MessageHelper;


/**
 * @Description:角色服务 
 * @author: lixu
 * @date:   2018年7月13日 下午2:53:44   
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    private SysRoleDao sysRoleDao;

    @Autowired
    private SysRolePermissionReDao sysRolePermissionReDao;

    @Autowired
    private SysPermissionDao sysPermissionDao;

    @Autowired
    private SysRoleMemberReDao sysRoleMemberReDao;

    @Autowired
    private MessageHelper messageHelper;


    /**
     * @Description: 添加角色
     * @param: @param sysRole
     * @param: @return      
     * @return: Long      
     * @throws   
     */
    @Override
    public Long addRole(SysRole sysRole){

        Assert.notNull(sysRole, messageHelper.getMessage(SecurityMessageCode.ROLE_NOT_NULL));//"sysRole can  not be null "

        // 检查指定的角色名是否是存在,存在抛出异常
        int count = this.sysRoleDao.selectCount(Condition.create().eq("name", sysRole.getName()));
        if (count > 0) {
            throw new BizBaseException(SecurityExceptionCode.ROLE_EXSITS);
        }
        // 验证通过， 入库
        sysRole.setCreatedate(new Date());
        Long id = IdWorker.getId();
        sysRole.setId(id);
        this.sysRoleDao.insert(sysRole);
        return id;
    }


    /**
     * @Description: 添加一个管理员角色
     * @param: @param sysRoleSystemDTO
     * @param: @return      
     * @return: Long      
     * @throws   
     */
    @Override
    public Long addRoleSystem(SysRoleSystemDTO sysRoleSystemDTO){
        Assert.notNull(sysRoleSystemDTO, messageHelper.getMessage(SecurityMessageCode.ROLE_NOT_NULL));//"sysRole can  not be null "
        // 检查指定的角色名是否是存在,存在抛出异常
        int count = this.sysRoleDao.selectCount(Condition.create().eq("name", sysRoleSystemDTO.getName()));
        if (count > 0) {
            throw new BizBaseException(SecurityExceptionCode.ROLE_EXSITS);
        }

        Long roleId = IdWorker.getId();
        // 验证通过,插入角色信息
        sysRoleSystemDTO.setCreatedate(new Date());
        sysRoleSystemDTO.setId(roleId);
        this.sysRoleDao.insert(sysRoleSystemDTO);
        Long memberId = sysRoleSystemDTO.getMemberId();

        //插入角色和人员的关系
        if (memberId != null) {
            SysRoleMemberRe roleMemberRe = new SysRoleMemberRe();
            roleMemberRe.setId(IdWorker.getId());
            roleMemberRe.setRoleId(roleId);
            roleMemberRe.setMemberId(memberId);
            roleMemberRe.setCreateDate(new Date());
            this.sysRoleMemberReDao.insert(roleMemberRe);
        }

        return sysRoleSystemDTO.getId();
    }

    /**
     * @Description: 编辑角色名称
     * @param: @param roleId
     * @param: @param roleName
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean editRoleName(Long roleId, String roleName){
        // 查询要编辑的角色名称在数据库中是否存在
        int count = this.sysRoleDao.selectCount(Condition.create().eq("name", roleName).and().ne("id", roleId));
        if (count > 0) {
            throw new BizBaseException(SecurityExceptionCode.ROLE_EXSITS);
        }
        // 不存在，则更新
        SysRole sysRole = new SysRole();
        sysRole.setName(roleName);
        sysRole.setId(roleId);
        return this.sysRoleDao.updateById(sysRole) > 0;
    }


    /**
     * @Description: 给memberid 赋予多个角色
     * @param: @param memberId
     * @param: @param roleIds
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean addMemberRoles(Long memberId, Long roleIds[]){
        Assert.notNull(memberId, messageHelper.getMessage(SecurityMessageCode.MEMBERID_NOT_NULL));//"memberId can  not be null "
        Assert.notNull(roleIds, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleIds can  not be null "
        Date date = new Date();
        // 循环检查是否存在
        for (Long roleId : roleIds) {
            EntityWrapper<SysRoleMemberRe> entityWrapper = new EntityWrapper<>();
            entityWrapper.and().eq("member_id", memberId).and().eq("role_id", roleId);
            // 不存在，则插入
            if (this.sysRoleMemberReDao.selectCount(entityWrapper) <= 0) {
                SysRoleMemberRe sysRoleMemberRe = new SysRoleMemberRe();
                sysRoleMemberRe.setId(IdWorker.getId());
                sysRoleMemberRe.setMemberId(memberId);
                sysRoleMemberRe.setRoleId(roleId);
                sysRoleMemberRe.setCreateDate(date);
                this.sysRoleMemberReDao.insert(sysRoleMemberRe);
            }
        }

        return true;
    }

    /**
     * @Description: 批量查询成员的角色列表
     * @param: @param memberIds
     * @param: @return      
     * @return: List<SysRoleDTO>      
     * @throws   
     */
    @Override
    public List<SysRoleDTO> listMemberRoles(Long memberIds[]) {
        Assert.notNull(memberIds,messageHelper.getMessage(SecurityMessageCode.MEMBERIDS_NOT_NULL));// "memberIds can  not be null "
        return memberIds.length == 0 ? null : this.sysRoleMemberReDao.listRoles(memberIds);
    }

    /**
     * 根据角色编号查询此角色下的所有的成员
     *
     * @param roleId
     * @param pageSize 每页大小
     * @param pageNo   当期页
     * @return
     */
    @Override
    public PageBean<SysRoleMemberRe> listMemberByRole(Long roleId, Integer pageSize, Integer pageNo){
        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleId can  not be null "
        EntityWrapper<SysRoleMemberRe> entityWrapper = new EntityWrapper<>();
        entityWrapper.and().eq("role_id", roleId);

        Page<SysRoleMemberRe> page = new Page<>(pageNo, pageSize);

        List<SysRoleMemberRe> list = sysRoleMemberReDao.selectPage(page, entityWrapper);

        page.setRecords(list);

        return PageBean.toPageBean(page);
    }
    
    /**
     * @Description: 根据角色编号删除角色
     * @param: @param roleId
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean deleteRole(Long roleId){
        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleId can not be  null "
        EntityWrapper<SysRoleMemberRe> entityWrapper = new EntityWrapper<>();
        entityWrapper.and().eq("role_id", roleId);
        return this.sysRoleMemberReDao.delete(entityWrapper) > 0;
    }

    /**
     * @Description: 角色添加成员
     * @param: @param roleId
     * @param: @param memberIds
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean addRoleMember(Long roleId, Long memberIds[]) {

        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleId can not be  null "
        Assert.notNull(memberIds, messageHelper.getMessage(SecurityMessageCode.MEMBERIDS_NOT_NULL));//"memberIds can not be  null"

        // 查询角色编号是否存在
        SysRole role = this.sysRoleDao.selectById(roleId);
        if (role == null) {
            throw new BizBaseException(SecurityExceptionCode.ROLE_NOT_EXISTS);
        }
        /**
         * 查询出当前角色下所有的成员
         */
        EntityWrapper<SysRoleMemberRe> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("role_id", roleId);

        List<SysRoleMemberRe> list = this.sysRoleMemberReDao.selectList(entityWrapper);

        List<Long> memberIdList = new ArrayList<>();
        for (SysRoleMemberRe sysRoleMemberRe : list) {
            memberIdList.add(sysRoleMemberRe.getId());
        }

        // 存在插入关系表
        for (Long memberId : memberIds) {
            if (memberIdList.contains(memberId)) {
                continue;
            }
            SysRoleMemberRe roleMemberRe = new SysRoleMemberRe();
            roleMemberRe.setId(IdWorker.getId());
            roleMemberRe.setRoleId(roleId);
            roleMemberRe.setMemberId(memberId);
            roleMemberRe.setCreateDate(new Date());
            this.sysRoleMemberReDao.insert(roleMemberRe);

        }

        return true;
    }

    /**
     * @Description: 角色删除成员
     * @param: @param roleId
     * @param: @param memberIds
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean deleteRoleMember(Long roleId, Long memberIds[]) {
        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleId can not be  null "
        Assert.notNull(memberIds, messageHelper.getMessage(SecurityMessageCode.MEMBERIDS_NOT_NULL));//"memberIds can not be  null"

        EntityWrapper<SysRoleMemberRe> entityWrapper = new EntityWrapper<>();
        entityWrapper.and().eq("role_id", roleId).and().in("member_id", memberIds);
        return this.sysRoleMemberReDao.delete(entityWrapper) > 0;
    }

    /**
     * @Description: 根据成员编号删除对应的角色关系
     * @param: @param memberIds
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean deleteRoleMembers(Long memberIds[]){
        Assert.notNull(memberIds, SecurityMessageCode.MEMBERIDS_NOT_NULL);//"memberIds can not be  null "
        if (memberIds.length > 0) {
            EntityWrapper<SysRoleMemberRe> entityWrapper = new EntityWrapper<>();
            entityWrapper.in("member_id", memberIds);
            return this.sysRoleMemberReDao.delete(entityWrapper) > 0 ? true : false;
        }

        return false;
    }

    /**
     * @Description: 角色添加权限
     * @param: @param roleId
     * @param: @param sysPermissions
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean addRolePermission(Long roleId, List<SysPermission> sysPermissions){
        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleId can not be  null "
        Assert.notNull(sysPermissions, messageHelper.getMessage(SecurityMessageCode.PERMISSIONS_NOT_NULL));//"sysPermissions can not be  null "
        EntityWrapper<SysRolePermissionRe> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("role_id", roleId);

        List<SysRolePermissionRe> permissionList = this.sysRolePermissionReDao.selectList(entityWrapper);
        List<Long> permissionIdList = new ArrayList<>();

        for (SysRolePermissionRe re : permissionList) {
            permissionIdList.add(re.getPermission_id());
        }

        List<Long> addPermissionIds = new ArrayList<>();
        // 循环构造对象 加入角色权限对应关系
        for (SysPermission sysPermission : sysPermissions) {
            Long permissionId = sysPermission.getId();
            //没有此权限项，才插入数据库
            if (!permissionIdList.contains(sysPermission.getId()) && !addPermissionIds.contains(permissionId)) {

                addPermissionIds.add(permissionId);

                SysRolePermissionRe rolePermissionRe = new SysRolePermissionRe();
                rolePermissionRe.setRole_id(roleId);
                rolePermissionRe.setPermission_id(permissionId);
                rolePermissionRe.setCreatedate(new Date());
                rolePermissionRe.setId(IdWorker.getId());
                rolePermissionRe.setPermissionCode(sysPermission.getPermissionCode());
                this.sysRolePermissionReDao.insert(rolePermissionRe);
            }
        }

        return true;
    }
    
    /**
     * @Description: 角色添删除权限
     * @param: @param roleId
     * @param: @param permissionIds
     * @param: @return      
     * @return: boolean      
     * @throws   
     */
    @Override
    public boolean deleteRolePermission(Long roleId, Long[] permissionIds){
        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL));//"roleId can not be  null "
        Assert.notNull(permissionIds, messageHelper.getMessage(SecurityMessageCode.PERMISSIONS_NOT_NULL));//"permissionIds can not be  null "

        Set<Long> idSet = new HashSet<>();
        List<SysPermission> sysPermissions = new ArrayList<>();
        for (Long permissionId : permissionIds) {
            SysPermission permission = new SysPermission();
            permission.setId(permissionId);
            sysPermissions.add(permission);
            idSet.add(permissionId);
        }
        if (permissionIds.length > 0) {
            EntityWrapper<SysRolePermissionRe> entityWrapper = new EntityWrapper<>();
            entityWrapper.and().in("permission_id", idSet).and().eq("role_id", roleId);
            return this.sysRolePermissionReDao.delete(entityWrapper) > 0;
        }
        return false;
    }

    /**
     * @Description: 根据角色ID查询关联的权限ID
     * @param: @param roleId
     * @param: @return      
     * @return: List<Long>      
     * @throws   
     */
    @Override
    public List<Long> listRolePermissionIds(Long roleId){
        Assert.notNull(roleId, messageHelper.getMessage(SecurityMessageCode.ROLEIDS_NOT_NULL)); //"roleId can not be  null "
        EntityWrapper<SysRolePermissionRe> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("role_id", roleId);

        List<SysRolePermissionRe> selectList = this.sysRolePermissionReDao.selectList(entityWrapper);
        List<Long> permissionIds = new ArrayList<>();
        if (selectList != null && !selectList.isEmpty()) {
            for (int j = 0; j < selectList.size(); j++) {
                permissionIds.add(selectList.get(j).getPermission_id());
            }
        }
        return permissionIds;
    }

    /**
     * @Description: 根据权限ID查询对应的权限项信息
     * @param: @param listRolePermissionIds
     * @param: @return      
     * @return: List<SysPermission>      
     * @throws   
     */
    @Override
    public List<SysPermission> listPermissions(List<Long> listRolePermissionIds){
        Assert.notNull(listRolePermissionIds, messageHelper.getMessage(SecurityMessageCode.PERMISSIONS_NOT_NULL));//"PermissionIds can not be  null "
        if (listRolePermissionIds.size() > 0) {
            EntityWrapper<SysPermission> entityWrapper = new EntityWrapper<>();
            entityWrapper.and().in("id", listRolePermissionIds);
            return this.sysPermissionDao.selectList(entityWrapper);
        }

        return Collections.emptyList();
    }

    /**
     * @Description: TODO
     * @param: @param memberIds
     * @param: @return      
     * @return: List<SysPermission>      
     * @throws   
     */
    @Override
    public List<SysPermission> listPermissionByMemberIds(List<Long> memberIds) {
        Assert.notNull(memberIds, messageHelper.getMessage(SecurityMessageCode.MEMBERID_NOT_NULL));//"memberId can not be  null "

        if (memberIds.size() > 0) {
            List<Long> permissionIds = new ArrayList<>();
            permissionIds.addAll(this.sysRolePermissionReDao.listPermissionIdByMemberIds(memberIds.toArray(new Long[memberIds.size()])));
            if (permissionIds.size() > 0) {
                EntityWrapper<SysPermission> entityWrapper = new EntityWrapper<>();
                entityWrapper.and().in("id", permissionIds);
                return this.sysPermissionDao.selectList(entityWrapper);
            }
        }
        return Collections.emptyList();
    }
    
    /**
     * @Description: 根据角色ID集合查询角色集合
     * @param: @param roleIds
     * @param: @return      
     * @return: List<SysRole>      
     * @throws   
     */
    @Override
    public List<SysRole> getSysRolesByIds(List<Long> roleIds) {

        if (!roleIds.isEmpty()) {
            EntityWrapper<SysRole> wrapper = new EntityWrapper<SysRole>();
            wrapper.in("id", roleIds);
            return sysRoleDao.selectList(wrapper);
        }
        return new ArrayList<SysRole>();
    }
}
